
			Writing New Modes, Menus and Packages


											  created: 97-03-03 11.44.50
										  last update: 12/13/2001 {18:58:24 PM}

Author:	Vince Darley, some pieces by Tom Fetherston and Pete Keleher
E-mail:	<vince@santafe.edu>
  mail:	317 Paseo de Peralta, Santa Fe, NM 87501, USA
   www:	<http://www.santafe.edu/~vince/>


	  	 Introduction

This document tells you how to write or modify code to add functionality to
Alpha or Alphatk.  Alpha 7.x, 8.x, Alpha X and Alphatk all rely upon the
AlphaTcl library to perform most tasks.  The AlphaTcl library in turn
provides an API (a set of procedures, variables, interfaces) by which you
can add new features.  If written correctly, such additions will work
seamlessly with any of Alpha 7.x, 8.x, Alpha X or Alphatk.

Examples of such additions may be to create a new mode, menu, add an item to
an existing mode or menu, or simply add some new functionality to existing
actions.  Collectively all such add-ons to Alpha are known as 'packages' or
'features'.  Individual packages may be referred to as modes, menus or
extensions depending upon their use.

This document also tells you how to make your package interact effectively 
with a few other commonly used packages which users might already be using.

There are two basic types of package which Alpha uses: modes, and 
features.  A mode helps with editing a file for a particular purpose: 
web pages use 'HTML' mode, C++ code uses 'C++' mode, LaTeX documents 
use 'TeX' mode, There are about 40 such modes currently available.  
Features are of three types: menus, extensions and ordinary features.  
A feature adds functionality to Alpha either globally (a 'global 
feature') or just for particular modes (a 'mode feature').  Menus are 
one type of feature used to extend Alpha, and aren't really much different 
to features which don't add menus: the only distinguishing difference is a 
couple of lines of code which do some menu creation/deletion.

Note: lines in this document which begin (*) are elaborations of previous
material which can be skipped first time through.

	  	   Package basics

All packages will contain a package identification and initialisation
command, called 'alpha::extension', 'alpha::mode', 'alpha::menu',
'alpha::feature', 'alpha::flag' as appropriate.  (One of the purposes of
this document is to describe the minor, but important differences between
these five).

Here are some examples:

	alpha::extension recentFilesMenu 0.4 ...

The menu of recent files, accessible from Alpha's File menu is an extension.
Extensions are only designed to be turned on and off globally (so you can't
use the recent files menu when in C++ mode but not when in HTML mode(*)), which
makes sense for this package, since a user will either want to have access
to the menu all the time, or not at all.  The number is the version of this
package; in this case version 0.4.  Notice this is declared as an extension,
not as a menu.  The 'alpha::menu' command is reserved for menus which appear
in Alpha's menubar, not submenus such as this.

(*) In fact the 'Config->Mode Prefs->Features...' dialog lets expert users
turn such global extensions off for particular modes, but this might cause
unforeseen problems.

Another example:

	alpha::feature latexAccents 1.0.5 {TeX Bib} ...

Some users of LaTeX find it easier to type accented characters ''
directly into their documents rather than somewhat esoteric control codes
like \'{e}.  This package makes that task a lot easier.  It is only useful
for LaTeX and BibTeX documents, so the author specifies that information in
an extra argument to 'alpha::feature' which is not allowed (or relevant)
for 'alpha::extension'.

Most modes add a menu which is automatically attached to that mode.  Other
menus are often useful globally.  It's up to the user to decide when each
feature/menu is active, although each feature can specify its default. 
Mode-authors can of course set the defaults for their mode.  Examples of
globally useful menus are the filesets menu, the mail menu and the
electric menu.  When you create a new menu for Alpha, you have the option
of suggesting that it is attached to particular modes, or that it is
suggested as global, or that it is global only.  General features are
organised in the same way, but don't create menus.  Finally, an extension
is a simple form of feature which is either globally active or off (it
either doesn't make sense or isn't particuarly useful to turn extensions on
and off in a mode-dependent way).  Examples of extensions are the printer
choices sub-menu, or the bib-engine (used to interact with BibTeX).  Note:
a 'menu' is something which sits in Alpha's menubar, at the top level.  A
feature or extension can create submenus which sit inside top level menus,
but these are not 'menus' in the same sense.  The main distinction is that
menus must be registered with 'alpha::menu' or 'addMenu', whereas submenus
need no special registration.

For the impatient reader: here's how to write a very simple feature 
which contains one new procedure and one new key-binding (to that 
procedure).  Just create a file which looks like this:

	# (auto-install) --- this line will cause Alpha to try to install 
	# this pkg when this file is opened outside of Alpha's folder hierarchy
	
	alpha::feature myPackage 0.1 {C C++} {
		# no global initialisation required
	} {
		# activation script
		# bind the 'x' key to my procedure (not a good idea ;-)
		Bind 'x' myProcedure
	} {
		# deactivation script
		unBind 'x' myProcedure
	} requirements {
	    # if your package has any strange requirements (such as 
		# particular versions of Alpha or it only runs on unix),
		# place code to test that here.  Otherwise omit this
		# section completely.
	    if {[info tclversion] < 10.0} {
	        error "My package requires Tcl 10!"
	    }
	} uninstall {this-file} maintainer {
		"My Name" my@email http://webpage..
	} help {
		Binds the blah-key to 'myProcedure' which carries out...
		
		This package is only designed to do something useful in
		C and C++ modes.
	}
	
	proc myProcedure {} {
		# do some cool stuff
	}
	
Save this file on your desktop (say), and open it.  You'll see Alpha
automatically opens an installation dialog, puts this file in the
right place if you agreed to the installation, and rebuilds its
package and tcl indices so that this package can be used next time
you restart Alpha (actually with a simple package like this, you can
use it straight-away).  By default this package declares it is useful
for C and C++ modes, although the user could choose to activate the
package globally or individually for any set of modes.

Important note: if you're writing a mode, menu or package, you should 
know about the 'package index'.  Alpha keeps a cache of all startup 
information, so that if you edit your 'alpha::mode ...' statement, and 
quit and restart Alpha, the changes will not take effect.  You must
tell Alpha to rebuild the package indices before quitting.

Alpha provides lots of cool facilities to help you write useful
packages, whether they are modes, menus or extensions.  This
document describes those facilities.

	  	   Guidelines for future compatibility

This section is useful if you're concerned about making future transitions
easier and giving your package the widest possible audience, however you may
wish to skip this section first time through.  Since Alpha will be upgraded
to Tcl 8 for the next major release (no date yet!), knowing this will save
you trouble later.  It will also help you to understand how to write code
which works efficiently with Tcl 8, making maximum use of the potential
speed improvements there.

When Alpha upgrades to Tcl 8, some changes to your code may be necessary, 
unless you pay attention to a few simple details.  

	  	     Namespaces

First, any proc which contains '::' is a procedure defined inside a
namespace.  Tcl 8 requires you to declare namespaces in advance.  Hence
unless Tcl 8 knows about namespace 'A', say, defining a procedure 'proc
A::blah ...'  is an error.  You should therefore include the line
'namespace eval A {}' at the beginning of the file defining all the 'A::'
procedures.  (Alpha 7.2 will ignore these namespace commands so your code
works either way)

	  	     Namespaces and infinite loops

The second guideline concerns the way namespaces actually work.
Assume you have defined two procedures 'A::open' and 'A::list'.
Let's say: 

	proc A::list {} { open [file join $HOME Help Changes] w ; ...}
	proc A::open {} { return [list a b c] }

Then both of these procedures will fail (and may crash Alpha) if 
running Tcl 8.  This is because inside the procedures we're in the 'A' 
namespace and this means commands are checked first to see if they 
exist inisde that namespace.  Therefore command 'open' in A::list is 
not the global Tcl command 'open', rather it is the procedure A::open 
(obviously not what was intended above).  Similarly 'list' in A::open 
is in fact the procedure A::list.  There are two ways to resolve this: 
(i) write 'list' as '::list' inside the proc (and 'open' as '::open'), 
or (ii) ensure the tail end of your procedures do not clash with any 
global Tcl commands.  The first option will not work in Tcl earlier 
than 8.0, which means you'd have to supply two different definitions 
of the procedure and use 'if {[info tclversion] < 8.0} ...'  to create 
the correct one.  The second option will work without modification, 
and is therefore somewhat preferable.

	  	     Variable-parameter name clashes

A third problem occurs quite rarely.  A variable such as 'index::flags'
is actually a variable 'flags' inside a namespace 'index'.  Under some
circumstances it is possible for a nameclash to occur.  For instance:

	proc test {flags} {
		global index::flags
		...
	}

Will throw an error 'Error: variable "flags" already exists' when
executed.  The easy solution is to rename the parameter passed in
(from flags to theFlags or whatever).  Name clashes can only happen
between function parameters and variables declared inside.  Note
that this behaviour is simply an extension of the more obvious
mistake in Tcl 7.x of 'proc test {flags} { global flags ... }'.

	  	     Directory delimiters

MacOS uses the colon ':' as a directory delimiter, so paths in Alpha
may be written as $HOME:Tcl:SystemCode:...  However, with the
forthcoming release of Mac OS X, the OS will have a unix underpinning,
and Alpha will use the MacOS X-native version of Tcl, which is
similarly unix based.  Hence the Tcl library within Alpha will then
use the forward-slash '/' as a directory delimiter.  The simple
solution is to use 'file join' 'file split' and ${file::separator} so 
that you don't assume any particular delimiter, and your code works
fine on all platforms.  The same issue arises with Alphatk
compatibility.

	  	     Other Tcl 8.x details

A final Tcl 8 issue is that lists are not parsed lazily as in Tcl 7.x.
So, grabbing an arbitrary string and doing 'lindex $string 0' in Tcl
7.x will usually return the first element of $string without an error,
even if $string is not a valid Tcl list (e.g. it contains unmatched {}
braces).  In Tcl 8 the entire string is first converted to a list, and
then the first element is extracted.  If the string is not a list, an
error will result.  The solution is only to use 'lindex/lrange/etc'
where you really have a list, and to use 'split' or 'regexp' or the
various 'string' commands when you need to manipulate strings.  For
example 'regexp "^\[^ \t\r\n\]+" $string firstElement' will usually
accomplish the same as 'lindex $string 0' (beware if $string may start 
with whitespace; you need a more complex regular expression).

By following these two guidelines, your code should continue to work
without any changes _at all_, when Alpha upgrades (except that your
code will run 2-10 times faster!).

If you're really concerned about maximum efficiency in Tcl 8, make
sure you always use '{}' with both 'if' and 'expr'.  This speeds things
up with Tcl 8 due to some technical aspects of the way the Tcl compiler
works (see http://www.scriptics.com for details).  For example don't
write 'if [expr 1+2 == 3] ...' but rather 'if {[expr {1+2 == 3}]}'.

A very important pointer for speed in Tcl 8 is that lists are very fast.
This means using 'lappend', 'lindex' etc is very quick.  There is one
small point you should obey: never use 'if {$myList == ""} {...}' to see
if a list is empty.  Instead use 'if {![llength $myList]} {...}'.  Until
Tcl implements some good optimisation in the internal compiler (which it
may never do), the former expression will slow your code down hugely when
the list isn't empty.

The behaviour of [file tail] has changed slightly between Tcl 7.5 (as used
by Alpha 6.x and 7.x) and 8.0; with 7.5 [file tail a:b:] was "", but 8.0
returns "b".  Try to write code which doesn't depend on this distinction.

The commands 'bind', 'menu', 'unbind' etc.  and all procedures in the
BackCompatibility.tcl file are obsolete.  Please do not use them.  At some
point in the future they will be removed completely.  In particular you
should realise that the compatibility procedures are slower than calling the
correct ones (especially 'menu' --- use 'Menu' instead), so you might as
well go through the effort of modernising your code now.  In addition there
have been many, many improvements and bug fixes to Alpha since 7.0/7.1/7.2,
so you'll save your end-user, yourself and the alphatcl-developers list a
lot of trouble if everyone is encouraged to upgrade to Alpha 7.3 or newer.

	  	   Guidelines for Alphatk compatibility

Related to the above is the recent release of Alphatk, a version of
Alpha which runs on Unix and Windows using the Tk toolkit.  If you want
your packages to function smoothly with Alphatk, make sure you obey
the following guidelines.  As an added benefit, if the windowing model
in Alpha changes in the future, if you follow these guidelines, your
code will still work.

Positions in Alphatk are not necessarily integers, in fact they may
contain all sorts of stuff (e.g. '5.0 lineend wordstart' is a valid
position in Alphatk).  Hence you can't use 'expr' to add/subtract
positions since they aren't numbers.  Also, since they may contain
spaces, you must be careful with 'concat', 'eval' etc which may break
them apart into multiple arguments (e.g. don't do something like 'eval
goto $pos').  Alpha provides the following 4 functions which you can use
instead, and which provide all the functionality you need (see "Alpha
Commands" for details):

	pos::math
	pos::compare
	pos::diff
	minPos

Provided you use these functions, your code will work unchanged across Alpha
7.x, Alpha 8.x and Alphatk.  Note that 'pos::compare' is not optional!  The
code 'if {$x == $y}' can return a different result to 'if {[pos::compare $x
== $y]}' on Alphatk (for example, if x is 4.3 and y is 4.30).

There are a few subtleties concerning the beginning and end of the window
and the behaviour of the above commands when dealing with positions which
don't exist (because they are before the beginning or after the end of the
window or line).  In these cases, the behaviour may vary between Alpha 7.x,
8.x and Tk.  Here is one example of this behaviour (if it becomes a regular
problem, we will fix things...).  Assume a line of text looks like this:

	HELLO THERE
	
with the cursor at the end of the line (after the E; assume there are no 
spaces). Then the effect of:

	set p [getPos]
	# Delete the 'ERE'
	deleteText [pos::math $p -3] $p
	set p [pos::math $p -3]
	deleteText [pos::math $p -1] $p
	
will be '    HELLO T' on Alpha 7, but '   HELL TH' on Alphatk.  This is
because the position 'p' after the first deleteText actually no longer
exists properly, and is therefore automatically moved backwards.  The
workaround is to adjust 'p' before deleting the text, since this
works on both Alpha 7 and Alphatk.  This problem occurs very rarely
(I've only seen it once in all of AlphaTcl), so it's not something to
worry about very much.  

One slightly more common occurence of this kind of problem is with the
beginning of the buffer.  In Alpha 7, 'pos::math [minPos] -1' will give
'-1', an artificial position before the beginning of the buffer (which might
be useful for code as an 'undefined position'), but in Alphatk, the same
code will actually return 1.0 (which is 'minPos') -- Alphatk will never
return an invalid position.  This means you are better off writing code
which doesn't use the -1 trick, since it won't work with Alphatk (and might
not work with a future version of Alpha, if we change the text rendering
engine).  An example of this problem used to lie in the completions
package, but since AlphaTcl 7.5 this has been rewritten to avoid use of -1.

Finally, Tk (and therefore Alphatk), uses many, many commands beginning
with '.' for all the gui elements created.  Therefore you should probably
steer clear of writing your own commands which start with a '.' (not that
anyone has ever tried to do this with Alpha!).

	  	   Declaring your package to Alpha

A package must contain, preferably as its first non-comment line (this 
is important), a statement like this:

	alpha::mode NAME VERSION ...
	
	alpha::menu NAME VERSION ...
	
	alpha::feature NAME VERSION ...
	
	alpha::extension NAME VERSION ...
	
(The other parameters to these commands are explained below).  The name will 
identify your package, and for modes must be at most 4 characters long.  
It should not contain any spaces (this limitation may be lifted in a future 
version of Alpha).  The version is a string of the form 1.0.1, or 2.3b1 or 
1.4.530.1.3a5.  Modes, menus and extensions take different arguments for the 
remainder of the 'alpha::' declaration line, but each ends in a script which 
Alpha scans and stores for you (Alpha scans all installed files for 
package declaration lines and caches this information so that at startup, 
no files need be read).  For modes and menus, this script is executed 
automatically at startup.  For features, there are initialisation and 
activation/deactivation scripts.  An extension is a simpler form of a 
feature which only has a single initialisation script (used the first 
time it is activated).  Package initialization occurs in the order: modes, 
menus and finally extensions.

IMPORTANT: The declaration command must not be wrapped in any 'catch' 
statements.  This is necessary to allow Alpha to rebuild package 
indices rapidly (note that it is no longer required to be at the 
beginning of the line).  If you wish to write backwards compatible code, 
try something like:

	if {[info commands alpha::extension] != ""} {
		alpha::extension ...
	} else {
		# initialize in some old way for Alpha 6.x
	}

Your package will not function properly if you don't obey the above 
guidelines.  Alpha itself is considered a package, with a version
number, so that your code can request a particular version of Alpha.
Alpha's version number also has a patchlevel which will be updated
with each Tcl-only patch release.  Hence you can write:

	alpha::package require Alpha 7.1b1

For the first Alpha 7.1 beta release, and

	alpha::package require Alpha 7.1p1

If your package actually requires some fixes from the first patch 
release after the final 7.1 release.  You can similarly require 
particular versions of other packages.  You should 'require' as old a 
version as possible, so that you don't force users to upgrade 
unnecessarily.

Note that with the advent of the new alpha:: commands, it is no longer
necessary to place modes, menus and packages in their separate directories:
they can go anywhere on the auto_path.  However it is more convenient to
store them separately most of the time.

	  	   The Alpha developer menu

You will want to activate/download this menu, since it helps with a 
number of developer-related tasks:

	debugging Tcl code
	rebuilding Tcl and package indices and rebuilding menus
	distribution archival, compression, and uploading
   creation of new modes/menu/features/extensions
	quick links to AlphaTcl related web sites.

	  	   Licensing issues

Obviously if you want to allow your code to be distributed with Alpha
and/or Alphatk, you need to license it under a compatible license
agreement -- one that allows free redistribution of your code.  The
most obvious choices are a 'Tcl/Tk/BSD' style license or a 'GNU' style
license, although other licenses are possible.  If your Tcl code is of
use with Tcl/Tk in general (i.e. not restricted to being used inside
Alpha/Alphatk), then you are strongly urged to use a Tcl-compatible
license, not a GNU license, since that is the norm in the Tcl
community.  Alpha and Alphatk come with various pieces of code
copyrighted and licensed under both of these licenses, although most
of the core AlphaTcl (i.e. excluding some standalone modes, menus and 
packages) is now licensed under a Tcl-style license.

	  	   Coding standards (tab sizes etc)

The core AlphaTcl library generally uses a tabsize of 8 but a visual
indentation of 4 (this is the default for Alpha, and also the standard for
Emacs and a lot of open-source projects in the unix world).  If you are
writing standalone packages for distribution with AlphaTcl there is no need
to abide by that convention, but individual procedures contributed to
AlphaTcl files will be (re)formatted according to that convention before
being applied.  Note that AlphaTcl contains facilities for individual files
or filesets to specify their default tabsize, so Alpha can quite happily be
made to work simultaneously on many different projects using different
tabsizes.

===============================================================================
	  	 
	  	 Writing New Modes

To add a mode to Alpha, a file (usually ending with 'Mode.tcl') must be 
created and placed in the ":Tcl:Modes" directory.  Please note that
the 'standard' tab size to be used in AlphaTcl is 8.  Of course
individuals can use whatever they want, but most existing code uses a 
tab-size of 8 (with an indentation amount of 4).

You may also wish to use the 'Config->Create New Mode...' helper to
set up the basics of your mode.

The file should begin with a construct of the following form:

	alpha::mode Perl 1.3 dummyPerl {*.pl *.ph *.pm} {
		perlMenu electricBraces electricReturn 
	} {
		addMenu perlMenu 132 Perl
	}

This command is very, very important.

	alpha::mode <mode> <version> <startupScript> <suffixes> <mode-features> <script>
	
defines a new mode.  The first time Alpha tries to switch to Perl mode, the
'startupScript' will be evaluated.  In this case this calls the procedure
'dummyPerl'.  This procedure is simply an empty procedure in the main
perlMode.tcl file.  The effect of evaluating it is to first autoload that
procedure: i.e. source the perlMode.tcl file.  Having done that the actual
procedure evaluation is rather irrelevant: hence the name 'dummyPerl'.
Subsequent switches to Perl mode will not need to source the file and so the
startup script is only ever evaluated once (historical note: before Alpha
7.4 it would be evaluated every time the mode was changed to Perl).  As a
simplification, you can use the word 'source' as a startupScript, and
AlphaTcl will source the file in which the alpha::mode statement occurs.
However, be careful with this.  If the file has already been sourced by some
other code, use of 'source' will still source the file again.  Therefore it
can be better just to use an empty dummy procedure as a way of ensuring the
file has been sourced once and once only.

The 'suffixes' allow Alpha to automatically determine the correct mode of a 
newly opened file.  In this case the script contains the single command:

	addMenu <mname> ?<name>? ?<pertains to modes>?

which defines a new menu, with 'name' the visible name of the menu (names 
which start with '' indicate Alpha should use an icon resource with the 
given number.  Icon number 132 is the Perl camel icon).  This menu can be 
used in any mode, although by default, it is only attached to Perl mode.  
'mname' is actually a variable which contains (will contain) the real menu 
name (in this case '132').  The third argument usually contains a 
single mode with which this menu is distributed.  Its use is mainly so that
Alpha knows that this menu belongs primarily to this mode, so that if the user
asks for information on the menu, Alpha knows to respond with 
information on the mode instead (curiously Alpha wouldn't otherwise 
know).

IMPORTANT: Perhaps the MOST important part of the above code is the
existence of the 'startupScript'.  When this proc is called, the result must
be that all of the mode's preferences are declared.  In other words, the
startupScript should ensure that the Tcl code containing all the 'newPref'
declarations is evaluated.  This is very, very important!

The normal way to do this is to have the 'startupScripts' be a dummy
procedure: e.g. 'proc dummyPerl {} {}' as above.  Tcl's autoloading
mechanism will then source the file containing that procedure.  Hence the
dummy procedure should normally be in the same file as the mode's 'newPref'
declarations.  This is important because almost directly after that call,
Alpha expects all of the mode's preferences to be stored in the
${mode}modeVars array, which will only be true if all of the newPref
commands have been evaluated.  IMPORTANT subtlety: the result of calling
'dummyProc/startupScript' must indeed be that all your newPref declarations
are executed.  As a result of this, the preferences will be stored in the
<mode>modeVars array, but will not yet be copied into the global scope (i.e.
the <mode>modeVars(myPref) array element will exist, but the global var
'myPref' will not yet exist).  Once your dummyProc/startupScript returns
(which generally means your mode's initialisation and sourcing of files is
complete), only then are the array entries copied into the global scope (in
the latter half of the changeMode proc).

Here is an example from Diff mode:

	alpha::mode Diff 1.0 diffMenu {*.diff} {diffMenu} {
		addMenu diffMenu 288
		menu::insert Utils submenu 0 compare
		menu::insert compare items end "windows" "files" "directories"
	} uninstall {
		file delete "$pkg_file"
		file delete [file join ${HOME} Tools "GNU Diff"]
	} maintainer { "Vince Darley" vince@santafe.edu http://... }

The 'uninstall' and 'maintainer' sections are optional, and explained later.  
Here is a more complex example for Python mode:

	#  minalmalist mode set-up  #
	alpha::mode Pyth 0.2 dummyPython {*.py *.pyc *.pyi} PythonMenu {
		addMenu PythonMenu
		#To set the mode from a unix-like "#!python" first line
		set unixMode(python) {Pyth}
	}
	# dummy proc to load this mode.  
	proc dummyPython {} {}
	# dummy proc to load the code to make the PythonMenu 
	proc PythonMenu {} {}
	# rest of mode's code follows...
	
	#Lets the automatic comment insertion/continuation
	# routines function with this mode. 
	set Pyth::commentCharacters(General) "\#"
	set Pyth::commentCharacters(Paragraph) [list "## " " ##" " # "]
	set Pyth::commentCharacters(Box) [list "#" 1 "#" 1 "#" 3]
	
The package declaration should contain all code which is necessary to 
recognise a given file as belonging to that mode (hence the use
of 'unixMode' for python), which will then make Alpha call the
dummyProc which will auto-load the entire file.  Other information,
such as the 'commentCharacters' entries above should not go in the
package declaration.
	
Notice that there are two types of 'dummy' proc; each menu Alpha uses
should have a proc of the same name associated with it.  This proc is
called by Alpha _each_ time Alpha tries to insert the menu into the
menubar.  The proc can be empty (as above), or could actually do
something if desired.  The second kind of dummy proc is the 'mode'
dummy proc, given in the 'alpha::mode' command.  Here it is called
'dummyPython'.  Alpha calls this proc the first time it switches to Pyth
mode.  Again the proc can do something if desired, but will usually
be empty.  If both procs are empty, as above, one can of course
just use one proc (called PythonMenu in this case), and replace the
alpha::mode line by:

	alpha::mode Pyth 0.2 PythonMenu {*.py *.pyc *.pyi} PythonMenu

The only advantage of this approach is that it saves a small amount
of memory (you can delete the 'dummyPython' proc from the file). Note that 
this only holds true for modes whose Tcl code is in one file.  
	
	  	   Multi-file modes

Modes that consist of more than a single file should no longer use a source 
statement that assumes that the other files for the mode will be in 
$HOME:Tcl:Modes.  The best solution is to use Alpha's standard auto-loading 
capability which will source a file when it needs a procedure which is 
contained in that file.  If you must use 'source' manually, you can use 
'file dirname [procs::find someProcInThisFile]' to get the current 
directory.  Your other files should also be there.

A convenient way of implementing your multi-file loading is to create
procs with the same name as the file at the beginning of each file.
Then to load the file you just do 'catch "filename"'.  For example
if there is a proc defined 'proc perl5.tcl {} {}' at the start of
the file "perl5.tcl", then I can auto-load that file by having the 
following code in "perlMode.tcl" (note: actual code differs slightly):

	if {[catch perl5.tcl]} { 
		alertnote "Problem loading 'perl5.tcl'" 
	}

Remember, you don't necessarily need to source all your mode/pkg's files in 
one go.  Tcl is designed to source files for you when they are needed (when 
a procedure contained in one of them is called).  Hence you only need to 
source files which are required immediately (to set up some data, variables, 
menus etc.)  and not everything else.  It is usually best to have a single 
file which contains all the initialization code, and let any other files be 
auto-loaded as necessary.


	  	   Use of the term "electric"

Through out the documentation and in actual proc names, you will see the use 
of the word "electric", so a note on its usage might be helpful. 
"Electric" is used in the sense of "automatic, power assisted behaviour", it is 
intended to save time, keystrokes, and brainpower. Such behaviour is usually
invoked by certain keystrokes (determined by various preference settings).


	  	   Mode procs

The following procs are either required or desired for a mode to be
fully functional within Alpha.

Marking Proc's:		(provide indexes into code via '{}' and "M' pop-ups)

	<mode>::parseFuncs   -- (not every mode provides this one)
	<mode>::MarkFile
	
Info providers:		(drive & support access to source or file related info)

	<mode>::DblClick	-- usually provides term specific help
	
	<mode>::optionTitlebar	-- provides menu to access related files
	<mode>::optionTitlebarSelect	-- action for menu selection above
	
electric behaviour:	(these assist formatting & and save on keystrokes)

	<mode>::carriageReturn	-- this, supported by the following two, help
							--  to keep indentation standard (indirectly 
							--  called by a carriage return).
	<mode>::indentLine -- indents a line by inserting spaces/tabs as 
	                   -- appropriate. If a 'correct indentation' proc
					   -- is given, then this procedure is not necessary.
	<mode>::correctIndentation -- allows smart-paste package to function.
	                   -- this procedure must never throw an error.

  -- These provide electric behaviour for '{', '}', and ';' respectively.
  --  Their use is primarily for languages that use '{' and '}' for code
  --  blocks, and ';' as the line terminator. They are indirectly called 
  --  by the key they correspond to, and then, only if a corresponding mode 
  --  preference flag has been defined and set to one. 
  --                      (see 'Electric braces and semicolons below)
  
	<mode>::electricLeft
	<mode>::electricRight
	<mode>::electricSemi

Have a look at a standard mode like Tcl or C++ to see what these
should do (in fact if you are writing your own mode, it is always
helpful to examine other modes and borrow from them).
	
	  	   Hooks

Do not do all that 'rename saveHook mySaveHook'... stuff.  Use 
'hook::register' instead. See the file "hook.tcl" for details, but all
you need to do is add lines like these:

	hook::register saveHook modified "C" "C++"
	hook::register saveHook modified "Pasc"
	hook::register saveHook htmlLastModified HTML
	hook::register savePostHook codeWarrior_modified "C++" "C"
	hook::register savePostHook ftpPostHook
	hook::register saveasHook htmlLastModified HTML

Here's the general form

	hook::register 'hook-name' 'your proc' 'mode' ?... 'mode'?

If you don't include a 'mode', then your proc will be called no
matter what the current mode is.   Avoid this unless absolutely
necessary.  Here are the current hooks:

	activateHook changeMode closeHook deactivateHook modifyModeFlags 
	quitHook resumeHook saveasHook saveHook savePostHook suspendHook
	openHook

There's also a 'mode::init' hook which will be called the first
time a mode is started up.  Note that at that time, the mode exists, but its
variables have not yet been made global, and its menus have not
yet been inserted into the menu bar.

There's also a 'startupHook' which is called when Alpha starts
up, but after all other initialization has taken place, a 'launch'
hook which is called when Alpha launches another application
(register with hook::register launch yourproc $sig).

	  	   Smart mode lines
	
If your mode will want to be able to use the first line of a file to 
determine what mode a file should be opened up in, you need to tell 
alpha what word in the first line should trigger that mode:
	
	set unixMode(python) {Pyth} 

A good place to do this is in the body of the your mode's package 
declaration "alpha::mode  {" statement (see example for Python above).  
Note that the presence of the word itself is not sufficient; it must be of 
the form '#!\usr\..\python' as is common on Unix (where it tells the shell 
with what application to run the script)

Note that there is already built in support for opening a file in a given 
mode if the first line contains:

	-*-<mode_label>-*-
	
e.g.:

	-*-Tcl-*-

Also, if the first line contains:

	(nowrap)

then you will not be asked if you want to see such a file in paragraph 
format simplly because the lines have gotten so long alpha thinks they 
might be from an application that maintains a paragraph as one long line 
and does its own wrapping internally.


	  	   Mode creator types
	
If your mode wants to declare itself as a default for files with a 
particular creator, (so any file with that creator opens up in that mode) 
you need to tell Alpha with an entry whoses format is like this:
	
	set modeCreator(<4_char_creator_code>) <mode_label>

e.g.:

	set modeCreator(McPL) Perl

A good place to do this is in the body of the your mode's package 
declaration "alpha::mode  {" statement.

	  	   Comment characters

If your mode will want to use the standard Alpha comment/uncomment
block procedures, file headers, ... you need to tell Alpha what
characters are used for comments.  Rather than redefining 
the procedure 'commentCharacters', you should just define the following 
variables:
	
	set ${mode}::commentCharacters(General) [list "*" "//"]
	set ${mode}::commentCharacters(Paragraph) [list "/* " " */" " * "]
	set ${mode}::commentCharacters(Box) [list "/*" 2 "*/" 2 "*" 3]
	
where the values shown are for C++ mode.  If you do this then there is
no need to mess with the commentCharacters procedure.  (In general it
is best if your mode does not need to redefine procedures in Alpha's core).

	  	   Paragraph definitions

Paragraph filling.  You can set the variables:

	set ${mode}::startPara {^(.*\{)?[ \t]*$}
	set ${mode}::endPara {^(.*\})?[ \t]*$}

to customize your mode's paragraph definition.  The above example's regular 
expressions (third 'word') are for Tcl code.

Alpha uses these to determine what it should act on when it is requested to 
re-wrap, make a selection or navigate with respect to paragraphs.  

Note that currently the wrapping routines take no notice of code formatting 
rules and are limited utility outside of the 'Text' mode.  The only proc's 
that use these are found in "textFill.tcl".

	  	   Electric braces and semicolon

If your mode uses electric '{', '}', ';' (i.e. characters that end the 
current line and indent the next one automatically) you need to define 
a few procedures: '${mode}::electricLeft', '${mode}::electricRight' 
and '${mode}::electricSemi' which will be called automatically (you do 
NOT need to bind anything to the keys).  If you do not define these 
procedures, Alpha will use a default electric procedure which works 
pretty well for C, Perl and Java code.

Of course the user needs to turn on the electric functionality for
your mode.  (Activate by default by including 'electricBraces' in 
your list of mode features in the alpha::mode command).

Do not bind to '{', '}' or ';' if you want these to be electric. Alpha
will automatically call your mode's procedures if they are named
correctly.

	  	   Option-click-titlebar menu

If your mode has a specific 'opt-titlebar-click' menu, you need to
define the procedures:
	
	proc C++::OptionTitlebar {} {
		# returns list of items for the menu
	}
	proc C++::OptionTitlebarSelect {item} {
		# carries out the mode-specific action when 'item' is selected.
	}

	  	   Electric code templates
	
If you mode wants to insert text into the window which contains template 
stops (usually bullets '' in Alpha), so that the user can move from
one to the next using the standard Alpha template packages (Alpha comes with 
a basic one, and more sophisticated ones build upon the same 
infrastructure), the you should insert template text with:

	elec::Insertion "blah blah  blah blah"

This is a simple example with a single template stop.  Template stops are 
noted with a pair of bullets (even though only one appears in the text).  
You can place between the pair of bullets some more information about the 
template stop, for instance:

	elec::Insertion "while \{condition\} \{\r\twhile body\r\}\r"

would be useful to insert a typical Tcl 'while' loop.  The template
packages can prompt the user with the explanatory text making code 
entry a little bit easier.

The 'elec::Insertion' routine works just like 'insertText' except it treats 
any item PROMPT as a template stop called 'PROMPT'.  This procedure takes 
a variable number of arguments, just like 'insertText'.  It has one further 
side-effect.  If there are any stops in the block, then the cursor is 
positioned at the first such stop.  Hence you don't need to do this: set p 
[getPos] ; insertText "blah..."  ; goto $p ; nextTabStop Instead you just do 
'elec::Insert "blah..."'.  Note that the procedure 'nextTabStop' no longer 
exists.  Use "ring::+", "ring::-" etc.  to move amongst tab stops.  The 
basic Alpha distribution contains only basic template support.  Install 
Vince's Additions to extend this support to persistent stops, with 
user-prompting in the text or status bar,...  You don't have to change your 
code to take advantage of the features of V'sA. It comes for free if you use 
'elec::Insertion' etc.

If you wish to use electric templates, avoid binding anything to the 'tab' 
key or the 'j' key (also opt-tab, cmd-tab,).  Such bindings may conflict
with the electric bindings.

To use electric templates, you'll want to add electricTab to your
list of default mode-features (or you can leave it for the user to
activate).  If your mode never wants the Tab key to indent, then 
define a dummy '<mode>::indentLine' proc which is empty: 
'proc <mode>::indentLine {} {}'.

	  	   Electric return

This allows pressing return to indent correctly for the following line 
so you may begin typing immediately.  To use this simply list this 
package in your mode's 'mode-features' list and, do _not_ bind to the 
return key.

	  	   Automatic indentation

Two variables are associated with a window's indentation scheme: 
'indentationAmount' and the window's tab-size (which can be read
with 'getWinInfo' or 'text::getTabSize').  If you are writing a custom 
indentation routine, the procedure 'indent::setup' will be useful 
to handle all these choices for you.  Look at the relevant section
of "globals.tcl" to see what that procedure sets up for you.  Most
people user either tab-size = indentation-amount = 4 spaces, OR
tab-size = 8, indentation-amount = 4 spaces.  These cases are quite
different, and it's nice if your mode allows the user to work with
their preferred setup.

	  	   The marks menu

Each mode has a procedure <mode>::MarkFile which is called to create the
popup 'M' menu of marks.  There is a global flag 'quietlyClearMarks'
which is set to 1 which dictates that the marks should be rebuilt
without prompting the user as necessary.  You can add a mode-pref
to over-ride this if you want.
Just what text-patterns are used to trigger the formation of a 'namedMark' 
(kept in the resource fork), its name, text position and extent, and the 
order in which they are present in the menu, is all determined by the 
<mode>::MarkFile your procedure.

For computer language editing modes, the common convention was to create an 
index by routine names for each routine defined in the file, and to present 
it in alphabetical order. The more current convention is to either 
hardwire, or present the user with the option of listing the routine names 
in the order in which they were defined in the file, indented under the 
name of the code section in which it was defined. 

The Tcl mode is a good example of the above, by default the defined Tcl 
proc's are presented in alphabetical order.  However if you check the 
'StucturalMarks' flag in Tcl's mode preferences, you get an index with the 
above format (after regenerating the index via the 'MarkFile' menuitem).  
If you organize your Tcl code into sections of logically or functionally 
related proc's, and then give them a short header by using the 
'InsertDivider' option under the Tcl Menu, you have an index that can be 
used to quickly get to a procedure when remember its position or 
functionality more than you do its exact name.

Of course, it is still often the case that you remember the name and just 
want to get to it quickly via an alphabetical index, so modes that use the 
above scheme usually provide an alphabetical listing via the '{}' popup, 
which is located right above the 'M' popup (see next topic).

Power User tip: cmd-clicking anywhere in a window's titlebar (except the 
exact center), or in the "bevel'ed frame" will give you the same menu as 
the 'M' popup. Using the sides of the window lets you access a particular 
area of the menu quicker as you can cmd-click in the approximate location 
of the index you want to go to. Additionally, if the window is flush 
against the lefthand edge of your monitor, it is easier to 'crash' your 
cusor into that edge and summon up the mark menu than it is to hit a eight 
inch square button.

	  	   The '{}' popup menu

This popup menu can be put to whatever use the mode author wants. If your 
are useing the scheme mentioned in the above section, it is good to use 
this popup to present an alphabetical listing of the routines. Some modes 
add extras such as indicating the number of arguments a routine expects 
(see Tcl), whether a argument is a 'reference' or a 'value' pass (see the 
M2, i.e. modula mode) or anything else that might be useful. Languages that 
use multi-part (qualified) identifiers may name the first part of a group 
of indentifiers and indent the rest of the identifiers that share that 
first part under it.

Power user tip: cmd-opt-<K> will put up a listpick dialog of the indexes 
under the '{}' popup, as this is usually alphabetical you can type the 
starting letters of the index you want to go to. (note: see 'Emacs Help' 
for some other tips to navigate any scrolling list dialog box.)



	  	   <mode>Completions.tcl

Each mode can have a completions file for use by the 'elecCompletions' 
package (part of Vince's Additions or available separately).  To use
this, place the appropriate definitions in a file called 
'<mode>Completions.tcl'.  The installer will place such files in the 
'Completions' directory automatically (provided you don't put them in 
a sub-folder of your distribution), and they will also be sourced
automatically the first time a file opens in your mode.  There is
therefore no need for you to source the file yourself.

===============================================================================

	  	 Writing new menus

New menus are placed in ":Tcl:Menus", and contain a start-up
section of much the same form as a mode or feature:

	alpha::menu ftpMenu	0.3 global "141" {
		# One-time initialisation script 
		
		# here we do nothing
	} {
		# Activation script
		
		# here we do the standard thing of calling the menu proc
		ftpMenu
	} {
		# Deactivation script
	}
	# proc ftpMenu to auto-load
	proc ftpMenu {} {}

The 'global' parameter tells Alpha that this menu isn't associated with
any particular mode (otherwise you can replace 'global' by a list of 
modes possibly including the global keyword, e.g. {global WWW HTML}).

Older versions of Alpha used to call a procedure with the same name
as the menu (here 'ftpMenu') automatically whenever the menu was to
be inserted.  The newer setup is a bit more verbose, but puts more
control in your hands.

NOTE: If all you want to do is add a submenu to an already existing
menu, go to the section 'Adding Items to Global Menus': you don't
need the 'alpha::menu' statement, but actually need to write a 
feature using 'alpha::feature'.

A menu-package is a set of code which builds and handles a standalone menu 
which the user may choose as a global menu.  Examples are the ftpMenu, 
filesetMenu, voodooMenu, internetConfigMenu, colorMenu and eudoraMenu (in 
fact this last item, since it has a mode associated with it, could in fact 
be rewritten as a mode with attached menu).  

Note: as of Alpha 7.1, you should use the command 'Menu -n ...' to build 
menus, not 'menu -n ...'
===============================================================================

	  	 Writing new features or extensions

An extension is a package which can be turned on once and then left 
alone.  Something which requires turning on/off for different modes is 
a feature.  In fact an extension is just implemented as a simple form 
of feature.  A new extension must provide at the very least the 
following line, preferably as the first non-comment line of one of its 
files:

	alpha::extension 'NAME' 'VERSION'
	
It is better, if possible, if the extension can provide a small script to 
carry out initialisation (which occurs when Alpha starts up, if the user
has turned the package on).  If provided Alpha will use that script 
rather than sourcing the entire extension file.  This means Alpha will
start up more quickly.  Such a script is given by the following line:

	alpha::extension 'NAME' 'VERSION' 'SCRIPT'
	
A feature is more sophisticated and takes arguments of the following 
form:

	alpha::feature 'NAME' 'VERSION' 'LIST OF MODES/GLOBAL' \
	  'INIT SCRIPT' 'ACTIVATE SCRIPT' 'DEACTIVATE SCRIPT'
	
Here is an example from the 'bibtexEngine' package:

	alpha::extension bibtexEngine 1.8 {
		eventHandler GURL GURL GURLHandler
	}

Here we didn't bother to turn the feature on and off, since its 
initialisation was so trivial, and it won't interfere with other 
modes at all.  Here's a more complex example:

	alpha::feature latexMathbb 1.0 {TeX Bib} {
	    newPref variable blackboardBoldSymbols "QZRN" TeX TeX::adjustMathbb
	    hook::register mode::init TeX::adjustMathbb TeX
	} "" ""

We didn't bother with activation deactivation, since the definitions 
don't take effect in other modes.  The simple 'extension' and 
'feature' commands make it very, very easy to extend Alpha's 
functionality without messing with the user's preferences file, 
without creating any '...+.tcl' extension files and without a complex 
installation process.  Alpha simply maintains a database of all 
'extension' scripts, and evaluates at startup all scripts for 
extensions which the user has activated.

	  	 Writing new extensions (keyboard caveats)

Writers of any package for Alpha should pay some attention to the 
problems which can arise with international keyboards.  Some bindings
are simply not available on some keyboards.  For instance, on some
keyboards, you need to use 'shift' to get the key '\' (unlike 
american keyboards where it is a single keypress).  On such a keyboard
there is no distinction between 'cmd-\' and 'shift-cmd-\'.  There is
no simple workaround for this problem.

Possibilities are: (i) check the current keyboard definition and adjust
bindings appropriately (based upon user feedback, presumably). (ii) let
the bindings be user-definable either by using 'newPref binding' to
define things, or by using a menu-scheme such as is used by HTML mode.

	  	 Technicalities of different menu/feature/extensions

Menus and features and extensions are all treated in the same way by
Alpha.  However each will have different associated information which
will determine whether/in what section it appears in a dialog box.
All this information is stored in the index::feature array.  

...to be continued...

===============================================================================
	  	 
	  	 Package preferences

Alpha stores preferences in three different places:

1)  Global preferences are stored in the 'Config->Preferences' menu, and
are for variables/flags which maintain a value at the global scope.

2)  Mode preferences are stored in the 'Config->Mode->Preferences' item, and
are for variables/flags which are stored in a mode array, but are transfered
into global scope when that mode is active (and hence temporarily override
any global preferences with the same names)

3)  Packages may add to the global/mode preferences as they desire.  They 
may also store preferences in their package array '${pkg}modeVars()'.  Such
variables/flags are never transfered into the global scope.  Menu items to 
edit a package's preferences should be placed in the 'global' menu, unless 
they are global/mode prefs which should be added to Alpha's default 
routines for use by the standard Alpha dialogs.  There is a standard proc

	package::addPrefsDialog Mypkg
	
which you can use to add an item to the global menu which will bring
up the standard dialog to edit the contents of your '${pkg}modeVars()'
array.

	  	   Adding to the core prefs dialogs

If you wish to add items to any of the core preferences pages (Backups,
Electric, Miscellaneous,...), you can do that like this:

	lunion varPrefs(Electric) var1 var2
	lunion flagPrefs(Electric) flag1 flag2

All non-registered global preferences are added to the Miscellaneous page,
so there is no need to do that automatically.  Make sure you don't add
too much to any of these pages, because they will become too large to
display correctly!

You can also add new core preferences pages.  All you have to do is create
a new 'flagPrefs' entry (Alpha uses the command 'array names flagPrefs' to
list the different pages):

	lunion flagPrefs(NewPage) flag1
	
Only add such pages if your package really does merit it; otherwise you're 
better off just add a new global preferences dialog in the global menu.
	
	  	   Defining a package's flags and variables

Preferences for a mode or package are defined as follows:

	# description of the preference
	newPref type name {val 0} {pkg "global"} {pname ""} \
		{options ""} {subopt ""}

Define a new preference variable/flag.

'type' is one of:
  'flag' (on/off only), 'variable' (anything), 'binding' (key-combo)
  'menubinding' (key-combo which works in a menu), 'file' (input only),
  'io-file' (either input or output), 'funnyChars'
  
'name' is the var name, 

'val' is its default value (which will be ignored if the variable
already has a value)

'pkg' is either 'global' to mean a global preference, or the name 
of the mode or package (no spaces) for which this is a preference.

'pname' is a procedure to call if this preference is changed by
the user (no need to setup a trace).  This proc is only called
for changes made through prefs dialogs or prefs menus created by
Alpha's core procs.  Other changes are not traced.

Depending on the previous values, there are two optional arguments
with the following uses:

TYPE:

variable:

'options' is a list of items from which this preference takes a single
item.
'subopt' is any of 'item', 'index', 'varitem' or 'varindex' or 'array', where
'item' indicates the pref is simply an item from the given list
of items, 'index' indicates it is an index into that list, and
'var*' indicates 'items' is in fact the name of a global variable
which contains the list. 'array' means take one of the values from an array.
If no value is given, 'item' is the default

binding:

'options' is the name of a proc to which this item should be bound.
If options = '1', then we bind to the proc with the same name as
this variable.  Otherwise we do not perform automatic bindings.

'subopt' indicates whether the binding is mode-specific or global.
It should either be 'global' or the name of a mode.  If not given,
it defaults to 'global' for all non-modes, and to mode-specific for
all packages.  (Alpha tests if something is a mode by the existence
of modeMenus($mode))

menubinding:

menubindings are like bindings, but they don't have any automatic
binding capabilities, and are restricted to key-sequences which the
MacOS allows in menus.  Here is an example of how one might declare
the 'QuickFind(Regexp)' dynamic pair using a menubinding pref:

declare the binding:

	Alpha  newPref menubinding quickFind/quickFindRegexp <B/S
	
edit it if we like with:

	Alpha  dialog::getAKey quickFind/quickFindRegexp <B/S
	
show the menu sequence if we like:
	
	Alpha  menu::bind quickFind/quickFindRegexp -
	<S<E<B/SquickFind <S<I<B/SquickFindRegexp
	Alpha  

add it to a menu:

	Alpha  eval menu::insert Search items end \
	    [menu::bind quickFind/quickFindRegexp -]
	
Have a look at the search menu.  It has a new dynamic item at the bottom!

funnyChars:

This is like 'variable', but provides for automatic decoding/encoding 
of tab, newline, carriage return into \t, \n, \r when the value is
displayed to the user.

Note that if you place a comment (one or more lines) just before the
'newPref' statement, it is scanned and stored by Alpha in a cache.  It
can then be used to explain to the user what each preference does when
the user selects 'describe mode' or presses the 'Help' button in a 
preference dialog.

	  	 Declaring help text for your preferences

Alpha has the ability to extract descriptive text for your preference
items automatically, provided they are declared using 'newPref', and
that you follow these guidelines.

If there is a comment (a line starting with '#') on the line/lines 
preceding the newPref command, Alpha will (when it rebuilds the package 
indices) store the text in that line/lines and use it to display helpful 
information for that preference.  For example if you hit the 'help' button 
in a dialog, Alpha will display this information.  Furthermore, in the 
forthcoming Alpha 8.0, this information will be used for balloon help in 
the prefs dialog related to your package/mode, provided you use the 
standard mechanisms for declaring your mode/menu/feature/extension and you 
use the standard preference mechanism supplied.  The format of the comment
lines is simple for all except basic flags (newPref flag ...).  These will 
display a different help text in balloons depending on their state.  There 
are four possible states, although Alpha only really uses the first and 
third such states at present.  The first state is the 'unchecked' state, 
and the third the 'checked' state.  You declare separate help text for the 
four possible states like this:

	# it is unchecked|it is dimmed|it is checked|it is checked and dimmed
	newPref flag myFlag ...

In fact all help items have four possible states, although you will 
usually not notice the other possibilities.  As you can see, Alpha uses '|' 
to separate the different pieces of text.  Currently a typical help text 
for a checkbox item should probably just look like this: 

	# To use a solid rectangular cursor, click this box||To use a thin 
	# vertical cursor, click this box.
	newPref flag blockCursor 0

Notice the syntax of the two messages.  Apple's interface guidelines
give some advice for balloon help which you should follow for two 
reasons: first, it's good advice for writing balloons, and second,
Alpha assumes your messages are of the above form to use the text
effectively both for balloons, and for descriptive text.  Alpha will
automatically convert the above to:

	Block Cursor: To use a solid rectangular cursor, turn this item on.  To
	use a thin vertical cursor, turn this item off.

which is used in the descriptive dialogs Alpha sometimes provides.  This 
advice is of greatest importance for 'flag' preference items, since they
require two separate on/off balloon help texts.  Other items currently
just expect one piece of text.  Each text item should be no longer than
255 characters.  The simplest balloon help methods impose this constraint
(in principle it could be relaxed, by using the more complex help methods
inside Alpha, but it doesn't seem necessary).

A similar mechanism will soon be available for menus.
	
	  	 Adding items to global menus

Using 'addMenuItem' is a bad idea, since many menus are dynamically
rebuilt and such items will be lost.  Furthermore, addMenuItem does
not work if you want to add dynamic items or sub-menus.  Also
creating a menu directly using 'Menu -n Name {list of items}' is
generally a bad thing to do when using Alpha version 7.0 or newer.

The solution to these problems is to use the following calls:

	menu::buildProc 'nameOfMenu' 'nameOfIts_build-proc' 
	menu::insert 'nameOfMenu' 'type' 'where' 'menuItem' ?menuItem...?

For technical reasons, if you use both types of call, always add the procs 
first.  You can add any list of menuItems using the latter of these two calls.  
The first registers a procedure which will be called to build a given menu.

Menus must be rewritten to support this new feature.  Currently all 
global menus File...Config support it, and several modes: Tcl, Perl, 
TeX.

	  	   menu::buildProc

This proc registers a procedure to be the 'build-proc' for a given menu 
(tech note: just adds the build-proc to the "menu_build_procs" global array 
with the given menu's name as its index).  The build-proc procedure can do 
one of two things:

i) build the entire menu, including evaluating the 'Menu ...' command.
In this case the build proc should return anything which doesn't
begin 'build ...'  

If the proc returns anything beginning with 'Menu ..' that returned 
string is evaluated, but no insertions can take place.

ii) build up part of the menu, and then allow pre-registered menu
insertions/replacements to take-effect.  In this case the procedure
should return a list of the following (listed by index in the list):

0: "build"
1: list-of-items-in-the-menu
2: menu procedure to call when an item is selected.  If nothing is given,
or if '-1' is given, then we don't have a procedure.  If "" is given,
we use the standard 'menu::generalProc' procedure.  Else we use the
given procedure.
3: list of submenus which need building.
4: over-ride for the name of the menu.

Here is an example of what gets returned by "menu::globalBuild", the 
build-proc for the menu named "global" (see Config:Global:):

		Alpha  menu::globalBuild
		0:	build 
		1:	{
				/p<U<BmenusAndFeatures 
							{Menu -n preferences {}} 
				editPrefsFile 
				(- 
				compareWindowsPrefs 
				newDocumentPrefs 
				(- 
				specialKeys 
				listGlobalBindings 
				listPackages 
				listAllBindings 
				listFunctions 
				(- 
				rebuildPackageIndices
			} 
		2:	menu::globalProc 
		3:	preferences
		
		Note: the above output was reformated and numbered to make its structure 
		explicit, also note that any additions to what you see in 'Config:Global:' 
		are due to calls to "menu::insert".

You must register the build-proc before attempting to build the menu (i.e. 
call menu::buildProc.  

Once registered, any call of 'menu::buildSome <name of your menu>' will 
build your menu.

	  	   menu::insert

nameOfMenu, type, where, then list of menuItems.  Here, type can be, either 
'items', or 'submenu'.

Add given items to a given menu, provided they are not already there.
Rebuild that menu if necessary.

There are also procs 'menu::removeFrom' which does the opposite of
this one, and 'menu::replaceWith' which replaces a given menu item
with others.

There is a difference between 'menu::insert Utils submenu 2 compare' and 
'menu::insert Utils items 2 [list Menu -n compare {}]'.  The former 
registers the submenu as a submenu which will be built automatically by a 
call to 'menu::buildSome' each time the parent menu is rebuilt, the latter 
does no such thing.  You will, therefore normally wish to use the first 
form, but occasionally there will be situations when the latter would be 
better.

Here is a simple example:

	alpha::extension compareWindows 0.1 {
		Bind 0x32    <X> compare::windowsInPlace
		Bind '1'  <X> compareOpt
		Bind 0x32    <sX> compareNext
		Bind 0x12    <sX> compareOptNext
		menu::insert Utils submenu 2 compare
		menu::insert "compare" items end windowsInPlace
	}

We first add a submenu after the second item in the Utils menu, called
'compare', and then add to the end of that compare menu. This code works 
whether the package is active at startup or not.  Here is a more 
complex example:

	alpha::extension documentProjects 1.2 {
		alpha::package require elecCompletions
		alpha::package require newDocument
		menu::buildProc "Current Project" Docproj::currentMenu
		menu::insert global items end \
			"documentProjectPrefs" "userDetails" \
			"<E<SremoveDocumentTemplate" "<S<BeditDocumentTemplate" \
			"<SnewDocumentTemplate" \
			"<E<SremoveProject" "<S<BeditProject" "<SnewProject"
		menu::insert global submenu end {Current Project}
		newPref binding updateFileVersion "/f<U" Docproj
		menu::insert fileUtils items end \
			"showInFinder" \
			"(-" \
			"updateDate" \
			"[menu::bind DocprojmodeVars(updateFileVersion) -]"
		lunion elec::MenuTemplates "createHeader" "newDocument"
		menu::insert elec items end \
			{Menu -n functionComments -p menu::fileUtils {
			"/efunctionComment"	
			"/e<IfunctionCommentSimple" 
			"/e<OfunctionCommentWithAuthor" 
			"/e<UfunctionCommentUpdate" 
		}}
		set newDocument::handlers(documentProjects) Docproj::newHandler
	}

The 'documentProjects' package adds items to many different menus,
including the 'elec' menu (from the elecCompletions package).

===============================================================================

	  	 Package testing

The 'alpha::package' command is very similar to Tcl 8.0's standard
'package' command, but differs in a few respects.  When Alpha upgrades
to Tcl 8, this will allow both features to coexist happily.  You can use
'alpha::package' to check/request the presence of other packages.

	alpha::package require NAME ?VERSION?
	
Other sub-commands are 'exists' 'names' 'versions' 'vcompare' 'vsatisfies'
'forget' 'uninstall' and 'mode', 'menu' and 'package'.  These last three
mimic the usual alpha::mode alpha::menu and alpha::package commands.

	alpha::package require ?-extension -mode -menu? name version
	alpha::package exists ?-extension -mode -menu? name version
	alpha::package names
	alpha::package uninstall name version [this-file|this-directory|script]
	alpha::package vcompare v1 v2
	alpha::package vsatisfies v1 v2
	alpha::package versions ?-extension -mode -menu? name
	alpha::package type name
	alpha::package info name
	alpha::package maintainer name version {name email web-page}
	alpha::package help name version [file 'name'|text]

Equivalent to alpha::mode, alpha::menu and alpha::extension

	alpha::package mode ...
	alpha::package menu ...
	alpha::package extension ...

For extensions only:

	alpha::package forget name version

..

===============================================================================

	  	 Installation

There is a new install mode 'Inst' which adds the Install menu.
Install mode is trigerred when a file's name ends in 'Install'
or 'INSTALL', or when the first line of the file contains the
letters 'install', provided in this last case, that the file
is not in Alpha's Tcl hierarchy.  This last case is useful so
that a single .tcl file can be a package and be installed by
Alpha using these nice scripts, without the need for a separate
install-script-file.  However once that .tcl file is installed,
if you open it you certainly wouldn't want it opened in Install mode!
	
So, single file packages should just include 'install' somewhere in
their first line.  Multi-file packages should include an install
file.  Call this file 'OPEN.TO.INSTALL' or something like that.
When the user opens it, Inst mode is activated, and the user can
use the install menu to install your package.  If you wish the
installation dialog to be activated automatically, include the
text (auto-install) in the first line of the file.

Most packages will _not_ need anything other than the existence of
such a file.  In fact a file called 'OPEN.TO.INSTALL' containing the
single line '(auto-install)' will do the trick nicely.

Alpha will scan the installation file directory and make a nice
dialog with 'Easy install' and 'Custom install' options.  Alpha
knows where Modes, Menus, Completions, Bug fixes, Tools, Packages,
Extensions, ... all go in the Alpha hierarchy.

In summary:

(1) If it's a single file package (e.g. smartPaste.tcl), simply include
'(auto-install)' in the first line of the file, and when the file is
opened Alpha will try to install it.

(2) If it's a multi-file package, create a file 'OPEN.TO.INSTALL'
containing a single line containing the text '(auto-install)' and place it
in the same directory as your other files.  When the user opens that file,
they'll get a nice installation dialog.  (You can also change its type to
'InSt' if you have resedit to get a nice icon).

More sophisticated things are possible, but usually not needed.  Note that
if you want to read an install file, rather than execute it, hold down
'option' when you double click on it.

Finally, in most cases, simply dropping files into Alpha's directory
hierarchy will work (and Alpha will notice they are there and rebuild
indices etc automatically).  However if a user is upgrading, rather than
installing such a package for the first time, Alpha will not notice the
change and not rebuild indices and this will probably cause problems.  
Hence this is not a recommended installation technique.

	  	   Package-specific installation over-rides

You can over-ride the default behaviour by providing a 'xxx_install.tcl'
file in the file directory.  In such a case that file will be sourced.
See "install.tcl" for some more information on how to over-ride the
default behaviour.  You will usually use the following procedure:

	install::packageInstallationDialog 'NAME' 'DESCRIPTION' ...

Optional arguments are as follows:
 
	-ignore {list of files to ignore}
	-remove {list of files to remove from Alpha hierarchy}	
	-forcequit '0 or 1'  
	    (forces the user to quit; default 0)
	-require {Pkg version Pkg version }
		e.g. -require {Alpha 7.0b1p2 elecCompletions 7.99}
	-provide {Pkg version Pkg version }
 
and 
 
	-SystemCode -Modes -Menus -BugFixes -Completions -Packages
	-ExtensionsCode -UserModifications -Tools -Home
 
which force the placement/use of the following lists of files.  To
require an exact package version use:

	-require {Alpha {-exact 7.0b2} elecCompletions {-exact 8.1.2} ...}

Also, rather than having separate 'OPEN.TO.INSTALL' and '*install.tcl'
files, if the former file contains the text 'auto-install-script' in
its first line, it will be used as a Tcl script, and sourced rather than
opened.  Ensure that first line begins with a '#' or an error will
result.  (You can open that file for editing, without triggering the
install script if you hold down a modifier key).

If you gave the -provide option, Alpha checks those items with what
the user has already installed and warns if an item has already been 
installed and is not older than the one about to be installed.

The '-forcequit' option may also take '2' as an argument, but this
is only used to update Alpha's core code: do not use this for your
own packages, since Alpha will not update the package indices
correctly.

	  	   Uninstalling packages

Each package should provide a 'alpha::package uninstall name version script' 
statement.  When your script is evaluated, the global variable 'pkg_file' 
will be initialised to the full name of the file which contains the 
uninstall command.  Therefore for a single file package, the following is 
normal:

	alpha::package uninstall developerUtilities 1.1 {file delete $pkg_file}

However, a much more convenient form of the above command is also possible, 
and most packages use it --- you may combine declaration and uninstall lines 
like this:

	alpha::extension developerUtilities 1.1 {
		# declaration script
	} uninstall {
		# uninstall script
	}
	
i.e. there are two extra optional arguments to the 'package' command.
Finally to be even simpler, if the command is 'uninstall this-file',
then that is equivalent to {file delete $pkg_file}, and if the command
is 'uninstall this-directory', then that entire file's directory is
removed.  Make sure you don't use 'uninstall this-directory' for a
single-file package, or you'll wipe out the entire package hierarchy.
Similarly alpha::mode and alpha::menu commands may contain an optional
uninstall script like the above.

	  	   Disabling packages

A package can add a script to be evaluated when the user disables the
package.  You do that with the additional command 'disable':

	alpha::extension developerUtilities 1.1 {
		# declaration script
	} disable {
		# disable script
	}

Complex packages will probably not provide such a script.  In such a
case the user would have to restart Alpha to disable the package
correctly.

	  	   Package requirements

As of AlphaTcl 7.5, a package can specify a separate script for testing
whether the current environment is suitable for the package.  This is
called a 'requirements' section:

	alpha::extension appleEventWizard 1.1 {
		# declaration script
	} requirements {
		# This package only runs on MacOS, and needs AlphaTcl 7.6
		if {$tcl_platform(platform) != "macintosh"} {
			error "The appleEventWizard only works on a Macintosh"
		}
		alpha::package require AlphaTcl 7.6
	}

Packages whose requirements fail cannot be activated in any of the
preferences dialogs, and are listed separately in the 'Packages'
help file, together with the reason that their requirements failed.
The user can then perhaps see that, say, the package would work if
they upgraded some component of Alpha, and may decide to do so.

Packages may be dependent on particular operating systems (MacOS,
Windows, Unix), on particular implementations of the editor (Alpha,
Alpha X, Alphatk), on particular versions of those implementations
(Alpha 7.3, Alpha 7.4, Alpha 8.0, etc), or on other packages (e.g. 
filesets 2.0).  You should try to make sure you don't pick a set
of requirements which are more restrictive than necessary, since that
will stop people from using the package on systems on which it should
work!  For example, Alphatk can in principle run on MacOS, and can
use the TclAE shared library, so if your package requires apple-events,
you should not assume it only works with Alpha, since it should also
work with Alphatk.  Also note that Alpha X actually uses the Unix
version of Tcl, so the value of tcl_platform(platform) will not be
macintosh!  (We may need to add an artifical 'MacOS' package to Alpha 
to simplify things for extension writers, so that they don't need to
worry about some of these subtleties).

	  	   Tcl index files

You probably know that Tcl uses 'index' files to find procedures which
are called but not yet defined.  Your installation directories may
contain index files if you desire, but they are only installed if no
current index file exists in the installation location.  You cannot
override this behaviour.

===============================================================================
	  	 
	  	 Miscellaneous Extras

This is primarily for new modes.  This section addresses ways in which a
mode can better interact with the following packages: better templates, new
document, electric bindings, electric completions, mode search paths,
function comments, developer utilities, electric menu, plus some others!
This section simply shows how you can make your mode/menu/extension aware of
these other packages, so that their functionality can be used effectively.

	  	   Source-Header files
	 
If your mode makes distinctions between 'Source' and 'Header' 
files, you should define these two variables

	newPref var sourceSuffices { .cc .cp .cpp .c .icc } C++
	newPref var headerSuffices { .h .hh } C++

	  	   Completions

If you mode is to use a variety of completion routines, define
an array entry like this:

	set completions(${mode}) \
		{completion::cmd completion::electric completion::word}

For the meaning of the list items, look at "elecCompletion.tcl".  If
all you need is the basic 'Command', 'Electric' and 'Word' completion
routines, the above list will do the trick.  You will then need to
define a variable ${mode}cmds like this:  

	set Ccmds { #elseif #endif #include class default enum for register return 
	 struct switch typedef volatile while }

It MUST be in alphabetical order.  For electric template insertions, you need
to create an array with entries like these:
	
	set Celectrics(for) " (init;test;increment)\{\n\tloop body\n\}\n"
	set Celectrics(while) " (test)\{\n\tloop body\n\}\n"
	set Celectrics(switch) " (value)\{\ncase item:\n\tcase body\ndefault:\n\tdefault body\n\}\n"
	set Celectrics(case) " item:\nɥcase body\ncase"

	  	   Mode-specific completions

If your mode has its own completion routines, they must be named
${mode}::Completion::Type, where 'Type' is an entry in the above
list.  You'll have to know a reasonable bit of Tcl to write your
own routines like that.  Look at C::Completion::Class for a relatively
simple example.

	  	   Electric menu templates

${mode}Templates is a list of names which are added to the electric 
menu's 'Templates' sub-menu.  The real procs should be called 
'file::${name}'.

	  	   Contextual Menu Help

This section is for Alpha 8 and newer only.  Alpha's event loop identifies a
CM event and passes the location to [contextualMenuHook] (it just passes a
position in the front window right now, but, based on the behavior of other
apps, it should either activate background windows and/or pass the window
name, too).  It passes either an 'null' AEDesc, or, based on the other
thread, expects the return of one created with [tclAE::createDesc].

[contextualMenuHook] will examine the position of the CM event and
compare it to the current selection.  If they're different, it will
create an AE object specifier for the click position in the document:
'character 2356 of window "AlphaBits.tcl"'.  If the click is within an
existing selection, it'll create an AE object specifier for the range
of the current selection 'from character 234 to character 875 of
window "www.tcl"'.  Either way, no intelligence to the context; just
characters.

Next, [contextualMenuHook] does [hook::callAll] to invoke any
registered CM hooks.  It'll pass the position and this context
descriptor.  Strictly, it only needs to pass the descriptor, but it
may be more efficient to pass the position, too.  These registered CM
hooks may then decide that they know more about the context than just
a range of characters.  A simple one might just note that whole words
were selected and replace the context with 'word 4 to word 7 of
paragraph 9 of window "thesis.tex"'.  Tcl mode's CM hook might change
it to 'line 3 of proc "contextualMenuHook" of window
"alphaHooks.tcl"'.  Johan could write one that would change it to
'anchor "acknowledgment" of window "HTMLManual.html"'.

CW 6 does this sort of thing (@%*!  eliminating command-double-click
in the process!), adding an item "Go to function definition of ..." 
or "Go to typedef declaration of..."  to the CM (I'm actually only
assuming that it changes the context descriptor as well, but it could
and should from what I can tell).

IM doesn't provide a hell of a lot of guidance here, saying:

  If the IsShowContextualMenuClick function returns true, you should
  call the ContextualMenuSelect function after generating your own menu
  and preparing an Apple Event descriptor (AEDesc) that describes the
  item for which your application is displaying a contextual menu.  This
  descriptor may contain an object specifier or raw data and will be
  passed to all contextual menu plug-ins.

I'm still puzzling through exactly how to implement object specifiers
in general, so when that becomes clear to me, this probably will, too.

	  	   Summary

That's it!  Take a look at "scilabMode.tcl" as a simple example of a new mode
which makes use of much of the above.
	  	 
	======================================================================

	  	 Embedding AlphaTcl

Alpha 7, 8, X and Alphatk are all applications which embed the AlphaTcl
library and use it to provide almost all functionality outside of the basic
editing window and core dialogs.  This section is here to document what that
actually means, since it isn't documented anywhere else.

Historically, (e.g. up to Alpha 7.x) embedding AlphaTcl has largely meant 
setting a HOME variable to the location of the AlphaTcl library files
and sourcing '[file join $HOME Tcl SystemCode AlphaBits.tcl]'.  As the
AlphaTcl library has become more complex, this startup sequence has been
retained, but it is probably time to add more flexibility.  This is 
particularly important because parts of the gui presented to the user
by the embedding application may be customisable by the user, yet all
preference handling (which it would be nice to use for that customisation) 
happens through the AlphaTcl library.  The solution implemented in AlphaTcl
as of versions 7.4.2 or newer, is to provide a pre-entry in AlphaTcl which
initialises and reads all of the users preferences.  These can then be
read by the embedding application to decide on the correct gui to display
(e.g. position of the status bar) and then initialisation of the rest of
AlphaTcl can proceed.

To achieve this, the embedding application must:

	set the HOME variable
	source [file join $HOME Tcl SystemCode initAlphaTcl.tcl]

now preferences are available, so the gui can be created. Then:

	source [file join $HOME Tcl SystemCode AlphaBits.tcl]
	
(this second step actually checks whether initAlphaTcl.tcl has been
sourced already, and if not will do so, thus allowing Alpha 7.x to
continue working with a single point of entry).

This two phase initialisation is used in Alphatk, and will be used by Alpha
8/X in the future.  We may want to gradually split AlphaTcl into a
directory containing the files required for the first phase, and another
set of directories for everything else.

We also need to document what command/variables beyond 'HOME' must be
created for the first phase to complete correctly.

     ====================================================================

	  	Changing Alpha's behavior
        

The rest of the manual discusses some general topics about how to extend
Alpha by writing your own Tcl code.


First of all, where do you put your own Tcl code so that Alpha can find it? 
Alpha has a set of preferences files for this purpose.  There is one global
preferences file which is loaded when Alpha is launched.  In this file you
should put code which should be loaded regardless of which mode you're
working in.  This preferences file is opened / created using the menu item
"Config --> Preferences --> Edit Prefs File".

Then there is one preferences file for each mode.  The file for a mode is
loaded after as the last code to be loaded when a mode is used the first
time.  This preferences file can be opened /created using the menu item
"Config --> Mode Prefs --> Edit Prefs File".

These preferences files are intended for code for personal use.  If you want
to write a complete new package for Alpha, which others also can use, of
course all the preceding information in this file is there to help you.


	  	Menus, user-defined
        

If you want to make your own menu with your personal Tcl functions, this
section explains how to do it.  If you want to add new menu items to the
existing menus, see the next section for instructions.  However, in that
case you also need to read this section.

Alpha's menu commands allow the user to build custom menus which contain
names of functions, macros, or arbitrary TCL commands that just HAVE to be
in the menus, as opposed to being merely callable through the bindings. 
The menu items are defined as a list of strings.  The following meta
characters can be embedded in the strings, and should be placed at the
beginning of the string:

	Meta-character     Usage
	--------------     -----

    ; or Return       Separates multiple items.
    ^                 Followed by an icon number, adds 
                      that icon to the item.
    !                 Followed by a character, marks the
                      item with that character.
    <                 Followed by B, I, U, O, E, or S,  
                      sets the character style of the item.
    /                 Followed by a character, sets up
                      a keyboard equivalent.
    (                 Disables the item. Use (- to get a 
                      separator line.

The following modifiers can be used to require other combinations of
modifiers than just the command key.  Control-option, for instance, is
specified by putting the string "<B<I" in the menu item.  The menu symbol
for shift is an upward outline arrow, control is the outlined ^ symbol
("Wins --> Iconify" has one), and option is the wavy line with the dot in
the upper right ("Search --> Replace All" has one).  The following are
characters that can follow the '<' and what they signify.

    B       - control key required
    I       - option key required
    U       - shift key required (only for alpha-numerics!)
    O       - command key required
    S       - is part of a dynamic item.
    E       - forces item to start new dynamic item.


A '/' followed by a character in the left column sets up a keyboard
equivalent for the key in the right column:

    a   Enter           n   F10
    b   Return          o   F11
    c   Tab             p   F12 
    d   Num Lock        q   F13
    e   F1              r   F14
    f   F2              s   F15
    g   F3              t   Help
    h   F4              u   Del
    i   F5              v   Forward Del
    j   F6              w   Home
    k   F7              x   End
    l   F8              y   Page Up
    m   F9              z   Page Down
    
The menu creation syntax is :

	Menu [-s] <-n name> <-i num> [-p procName] [-m] [-M <mode>] "Tcl list of menu items"

Where the arguments have the followings meanings:

  -s            Use system menu definition proc (faster).
  -i <num>      Resource id of icon suite to use for menu title.
  -n <name>     Name of menu.
  -m            No menu form. If not supplied, each menu item is split into 
                words at each capitalized letter.
  -p <pname>    Rather that having alpha call a Tcl proc named by the menu 
                item's text, this option tells Alpha to call the tcl proc 
                named by 'pname' with two arguments: the menu name, and the
                text of the menu item chosen.
  -M <mode>     Bindings only take effect in specified mode.
  
The 'Tcl list of menu items' can include another menu definition allowing
you to create hierarchical menus.  Once the menus are created, they can be
inserted and deleted from the menu bar by the syntax:

	insertMenu "name"
	removeMenu "name"

As alluded to above, Alpha attempts to make procedure names readable in the
menus by separating words at any capitalized letter.  For example,
'findFile' becomes "Find File".  This function is turned off by the '-m'
option.

Menu items can be enabled and disabled through the TCL command
'enableMenuItem'.  Menu items checkmarks can be turned on and off via
'markMenuItem'.  Menu items can be appended via 'addMenuItem' and deleted
via 'deleteMenuItem'.  See the "Alpha Commands" help file for syntax.

As explained above, Alpha uses various keys to specify text style and key
equivalents.  Sometimes you may want these characters included in your text
literally.  If an ampersand ('&') is the last character in a menu item,
these special characters are not interpreted.

If an ellipsis ('') is the last character in a menu item (except possible
for the above ampersand), it is stripped off before searching for the
function corresponding to the chosen item.


	  	Modifying Alpha's menus
        

Alpha's global menus and most mode menus can be modified using commands
menu::insert, menu::removeFrom, and menu::replaceWith.  The use of these
are explained in the section Adding items to global menus in the file
"Extending Alpha".


	  	Event hooks
        

When certain events occur.  e.g. when opening and closing windows, Alpha
calls an event hook.  You can register your own event hooks to add to the
default behavior when the corresponding event occurs.  Below is a table of
all available hooks.

To add your own hook there are two things you have to do.  First write a
proc to be called when some events occurs.  This proc must have the
parameters shown in the table.  Lets say you want to define a saveHook. 
Then define some proc

	proc mysaveHook {name}{
	    .
	    .
	}
    
The next thing you have to do is to register the proc.  This is done with a
line like:

	hook::register 'hook-name' 'your proc' 'mode' ?... 'mode'?

The optional mode parameters specify in which modes the hook will be
called.  If no mode parameters are given the hook will be called regardless
of the mode.  Avoid this unless absolutely necessary.

Let's assume that you want your hook to be called in TeX and Perl modes. 
To register it you would use the line:

	hook::register saveHook mysaveHook TeX Perl

Note, however, that a few hooks doesn't use the mode to determine when to
be called and should be registered slightly differently, see below.
    

	  	 	Window hooks

	Hook                                              Parameter(s)

 activateHook                                      path to file
  Called when a window is brought to front
 deactivateHook                                    path to file
  Called when a window is sent to back
 openHook                                          path to file
  Called when a window is opened
 closeHook                                         path to file
  Called when a window is closed
 saveHook                                          path to file
  Called when a window is saved
 saveasHook                                        path to old file, path to new file   
  Called when a window is saved as
 savePostHook                                      path to file
  Called after a window is saved
  
	  	 	Alpha hooks

	Hook                                              Parameter(s)

 startupHook
  Called at the end of startup
 quitHook
  Called when quitting Alpha
 suspendHook                                       an empty string
  Called when switching to another app
 resumeHook                                        an empty string
  Called when switching to Alpha from another app
  
	  	 	Mode hooks

	Hook                                              Parameter(s)

 mode::init
  Called the first time a mode is loaded
 changeMode                                        new mode
  Called when the mode is changed
 dialog::modifyModeFlags                           a string (title of dialog)
  Called after a mode prefs dialog is closed
 mode::editPrefsFile
  Called when a mode prefs file is opened 
  for editing
  
	  	 	Keyboard hooks

	Hook                                              Parameter(s)

 keyboard
  Called at startup and when the keyboard prefs 
  is changed
 removekeyboard
  Called when the keyboard prefs is changed
  
The keyboard hooks use the keyboard name (the ones in the keyboard popup
menu in the International preferences dialog) rather than the mode to
determine when to be called.  Thus to register a keyboard or removekeyboard
hook use lines like:

	hook::register 'hook-name' 'your proc' 'keyboard name' ?... 'keyboard name'?

	  	 	Miscellaneous hooks

	Hook

 launch
  Called when a helper app is launched by calling app::ensureRunning
  
The launch hook uses the application signature rather than the mode to
determine when to be called.  Thus to register a launch hook use a line
like:

	hook::register launch 'your proc' 'signature' ?... 'signature'?

 requireOpenWindowsHook    
  Called when opening and closing windows.

This hook is used to en-/disable meaningless menu items which would require
the presence of a certain number of windows to be active.  You can register
your own menu items using a line like:

	hook::register requireOpenWindowsHook [list menu item] N

where 'N' is the number of windows required (1 or 2 usually)

As an example, this is a line from Diff mode registering the item 'Compare
Windows' to require 2 open windows to be enabled.

	hook::register requireOpenWindowsHook [list compare windows] 2


	----------------------------------------------------------------------


	  	modeCreator

The modeCreator array allow you to tell Alpha which mode to choose when you
open a window depending on which application has created the file.  Add to
this array with lines like:

	set modeCreator(<signature>) <mode>
    
'Signature' is the signature of the application which has created the file
and 'mode' is the mode which you want Alpha set for the window.  For
example, to open all files created by Netscape in HTML mode use the line:

	set modeCreator(MOSS) HTML
    
Tip: To find the signature of an application, launch it, open the Tcl shell
(command-Y,) and type 'ps' at the prompt.  This will list all running
applications; the second column lists the signatures.

(Or click here --> <<shell; insertText "ps" ; Shel::carriageReturn>>)


	  	unixMode


When you open unix files where the first non-empty line reads
'#!/dir/subdir/command ...'  then Alpha tries to find a mode corresponding
to 'command'.  With the unixMode array you can tell Alpha which mode to
choose when opening such a file.  Add to this array with lines like:

	set unixMode(<command>) <mode>
    
where 'command' is the command in the line '#!/dir/subdir/command ...'  and
'mode' is the mode which you want Alpha set for the window.  For example,
to make Alpha open files with a line '#!/dir/subdir/perl ...'  in Perl mode
use the line:

	set unixMode(perl) Perl

